// Database.h
#ifndef DATABASE_H
#define DATABASE_H

#include <string>
#include <vector>
#include <mutex>
#include <sqlite3.h>
#include <stdexcept>

namespace ebackup {
namespace plugins {

class Database {
public:
    Database(const std::string& dbFilePath);
    ~Database();

    void initialize();
    void storeVirtualMachine(const VirtualMachine& vm);
    void storeBackupPolicy(const BackupPolicy& policy);
    void storeRecoveryPoint(const RecoveryPoint& point);
    std::vector<VirtualMachine> getVirtualMachines();
    std::vector<BackupPolicy> getBackupPolicies();
    std::vector<RecoveryPoint> getRecoveryPoints();

private:
    std::string dbFilePath_;
    sqlite3* db_;
    std::mutex dbMutex_;

    void executeQuery(const std::string& query);
    void createTables();
};

} // namespace plugins
} // namespace ebackup

#endif // DATABASE_H








// Database.cpp
#include "Database.h"
#include <iostream>
#include <sqlite3.h>
#include <stdexcept>

namespace ebackup {
namespace plugins {

Database::Database(const std::string& dbFilePath)
    : dbFilePath_(dbFilePath), db_(nullptr) {
    initialize();
}

Database::~Database() {
    sqlite3_close(db_);
}

void Database::initialize() {
    int rc = sqlite3_open(dbFilePath_.c_str(), &db_);
    if (rc) {
        throw std::runtime_error("Failed to open database: " + std::string(sqlite3_errmsg(db_)));
    }
    createTables();
}

void Database::storeVirtualMachine(const VirtualMachine& vm) {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::string query = "INSERT INTO VirtualMachines (name, cpus, memory_mb, state) VALUES ('" +
                        vm.name + "', " + std::to_string(vm.cpus) + ", " +
                        std::to_string(vm.memory_mb) + ", '" + vm.state + "');";
    executeQuery(query);
}

void Database::storeBackupPolicy(const BackupPolicy& policy) {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::string query = "INSERT INTO BackupPolicies (type, schedule, retention_days) VALUES (" +
                        std::to_string(policy.type) + ", '" + policy.schedule + "', " +
                        std::to_string(policy.retention_days) + ");";
    executeQuery(query);
}

void Database::storeRecoveryPoint(const RecoveryPoint& point) {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::string query = "INSERT INTO RecoveryPoints (id, timestamp, type) VALUES ('" +
                        point.id + "', '" + point.timestamp + "', " +
                        std::to_string(point.type) + ");";
    executeQuery(query);
}

std::vector<VirtualMachine> Database::getVirtualMachines() {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::vector<VirtualMachine> vms;
    std::string query = "SELECT name, cpus, memory_mb, state FROM VirtualMachines;";
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(db_, query.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        throw std::runtime_error("Failed to prepare query: " + std::string(sqlite3_errmsg(db_)));
    }
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        VirtualMachine vm;
        vm.name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        vm.cpus = sqlite3_column_int(stmt, 1);
        vm.memory_mb = sqlite3_column_int(stmt, 2);
        vm.state = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
        vms.push_back(vm);
    }
    sqlite3_finalize(stmt);
    return vms;
}

std::vector<BackupPolicy> Database::getBackupPolicies() {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::vector<BackupPolicy> policies;
    std::string query = "SELECT type, schedule, retention_days FROM BackupPolicies;";
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(db_, query.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        throw std::runtime_error("Failed to prepare query: " + std::string(sqlite3_errmsg(db_)));
    }
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        BackupPolicy policy;
        policy.type = sqlite3_column_int(stmt, 0);
        policy.schedule = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        policy.retention_days = sqlite3_column_int(stmt, 2);
        policies.push_back(policy);
    }
    sqlite3_finalize(stmt);
    return policies;
}

std::vector<RecoveryPoint> Database::getRecoveryPoints() {
    std::lock_guard<std::mutex> lock(dbMutex_);
    std::vector<RecoveryPoint> points;
    std::string query = "SELECT id, timestamp, type FROM RecoveryPoints;";
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(db_, query.c_str(), -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        throw std::runtime_error("Failed to prepare query: " + std::string(sqlite3_errmsg(db_)));
    }
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        RecoveryPoint point;
        point.id = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        point.timestamp = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        point.type = sqlite3_column_int(stmt, 2);
        points.push_back(point);
    }
    sqlite3_finalize(stmt);
    return points;
}

void Database::executeQuery(const std::string& query) {
    char* errMsg = nullptr;
    int rc = sqlite3_exec(db_, query.c_str(), nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::string error = "Failed to execute query: ";
        if (errMsg) {
            error += errMsg;
            sqlite3_free(errMsg);
        }
        throw std::runtime_error(error);
    }
}

void Database::createTables() {
    const char* createVMTable = "CREATE TABLE IF NOT EXISTS VirtualMachines ("
                                "name TEXT PRIMARY KEY, "
                                "cpus INTEGER, "
                                "memory_mb INTEGER, "
                                "state TEXT);";
    const char* createPolicyTable = "CREATE TABLE IF NOT EXISTS BackupPolicies ("
                                    "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                                    "type INTEGER, "
                                    "schedule TEXT, "
                                    "retention_days INTEGER);";
    const char* createPointTable = "CREATE TABLE IF NOT EXISTS RecoveryPoints ("
                                   "id TEXT PRIMARY KEY, "
                                   "timestamp TEXT, "
                                   "type INTEGER);";
    executeQuery(createVMTable);
    executeQuery(createPolicyTable);
    executeQuery(createPointTable);
}

} // namespace plugins
} // namespace ebackup